package net.nagaseyasuhito.nicola.service.impl;

import java.util.List;

import net.nagaseyasuhito.nicola.entity.User;
import net.nagaseyasuhito.nicola.service.UserService;

import org.apache.commons.codec.digest.DigestUtils;

import com.wideplay.warp.persist.Transactional;

public class UserServiceImpl extends BaseServiceImpl implements UserService {
	@Override
	@Transactional
	public User findById(Long id) {
		String query = "from User where id = :id";

		return (User) this.createQuery(query)
			.setParameter("id", id)
			.getSingleResult();
	}

	@Override
	@Transactional
	public User findByName(String name) {
		String query = "from User where name = :name";
		
		return (User) this.createQuery(query)
			.setParameter("name", name)
			.getSingleResult();
	}

	@Override
	@Transactional
	public User findByNameAndPassword(String name, String password) {
		String query = "from User where name = :name and password = :password";
		
		return (User) this.createQuery(query)
			.setParameter("name", name)
			.setParameter("password", DigestUtils.md5Hex(password))
			.getSingleResult();
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional
	public List<User> findFriendsByUser(User user, int firstResult, int maxResults) {
		String query = "select friend from User user join user.friends friend where user.id = :id order by friend.id";
		return (List<User>) this.createQuery(query, firstResult, maxResults)
			.setParameter("id", user.getId())
			.getResultList();
	}

	@Override
	@SuppressWarnings("unchecked")
	@Transactional
	public List<User> findFansByUser(User user, int firstResult, int maxResults) {
		String query = "select user from User user join user.friends friend where friend in (from User where id = :id) order by user.id";
		return (List<User>) this.createQuery(query, firstResult, maxResults)
			.setParameter("id", user.getId())
			.getResultList();
	}

	@Override
	@Transactional
	public boolean contains(User user, User targetUser) {
		String query = "select count(*) from User user join user.friends friends where user.id = :id and friends.id = :targetId";
		
		return ((Long) this.createQuery(query)
			.setParameter("id", user.getId())
			.setParameter("targetId", targetUser.getId())
			.getSingleResult()) != 0;
	}

	@Override
	@Transactional
	public void signUp(User user) {
		this.entityManager.persist(user);
	}

	@Override
	@Transactional
	public void follow(User user, User followUser) {
		String query = "insert into User__User_ (user__id, friends_id) values (:id, :followId)";
		this.entityManager.createNativeQuery(query)
			.setParameter("id", user.getId())
			.setParameter("followId", followUser.getId())
			.executeUpdate();
	}

	@Override
	@Transactional
	public void unfollow(User user, User unfollowUser) {
		String query = "delete from User__User_ where user__id = :id and friends_id = :unfollowId";
		this.entityManager.createNativeQuery(query)
			.setParameter("id", user.getId())
			.setParameter("unfollowId", unfollowUser.getId())
			.executeUpdate();
	}
}
